﻿using OxyPlot;
using OxyPlot.Axes;
using OxyPlot.Series;
using System;
using System.ComponentModel;
using System.Linq;
using System.Numerics;

namespace Data_Moni
{
    public class MainViewModel : INotifyPropertyChanged
    {
        private string _maxMinText;
        private string _harmonicsText;
        private PlotModel _plotModel;

        public string MaxMinText
        {
            get { return _maxMinText; }
            set
            {
                _maxMinText = value;
                OnPropertyChanged(nameof(MaxMinText));
            }
        }

        public string HarmonicsText
        {
            get { return _harmonicsText; }
            set
            {
                _harmonicsText = value;
                OnPropertyChanged(nameof(HarmonicsText));
            }
        }

        public PlotModel PlotModel
        {
            get { return _plotModel; }
            set
            {
                _plotModel = value;
                OnPropertyChanged(nameof(PlotModel));
            }
        }

        public MainViewModel()
        {
            AnalyzeAndPlotData();
        }

        private void AnalyzeAndPlotData()
        {

            Random random = new Random();
            double random_A = random.NextDouble();
            // 参数设置
            double A = 2.0 + random_A;  // 振幅
            double f =  1.0/3.0;  // 频率 (1/3 Hz, 即3秒转一圈)
            double phi = 0.0 + random_A*5;  // 相位
            int samplingRate = 60;  // 每秒采样点数
            int T = 18;  // 一个周期时间 (秒)
            int numSamples = samplingRate * T;  // 样本总数

            double[] time = new double[numSamples];
            double[] displacement = new double[numSamples];

            //Random random = new Random();
            // 生成数据
            for (int i = 0; i < numSamples; i++)
            {
                time[i] = i / (double)samplingRate;
                double randomValue = random.NextDouble();
                displacement[i] = A * Math.Sin(2 * Math.PI * f * time[i] + phi) + randomValue;
            }

            // 计算最大值、最小值及其对应的角度
            double maxValue = displacement.Max();
            double minValue = displacement.Min();
            int maxIndex = Array.IndexOf(displacement, maxValue);
            int minIndex = Array.IndexOf(displacement, minValue);
            double maxAngle = 360.0 * time[maxIndex] / T;
            double minAngle = 360.0 * time[minIndex] / T;

            // 计算一次谐波和二次谐波
            Complex firstHarmonic = CalculateHarmonic(displacement, 1, numSamples, T);
            Complex secondHarmonic = CalculateHarmonic(displacement, 2, numSamples, T);

            // 更新绑定数据
            MaxMinText = $"Max Value: {maxValue:F4} at {maxAngle:F2}°\n" +
                         $"Min Value: {minValue:F4} at {minAngle:F2}°";
            HarmonicsText = $"First Harmonic: {firstHarmonic.Magnitude:F4}\n" +
                            $"Second Harmonic: {secondHarmonic.Magnitude:F4}";

            // 绘制图表
            var plotModel = new PlotModel { Title = "Wheel Runout Over Time" };
            var lineSeries = new LineSeries { Title = "Displacement" };
            for (int i = 0; i < numSamples; i++)
            {
                lineSeries.Points.Add(new DataPoint(time[i], displacement[i]));
            }
            plotModel.Series.Add(lineSeries);
            plotModel.Axes.Add(new LinearAxis { Position = AxisPosition.Bottom, Title = "Time (s)" });
            plotModel.Axes.Add(new LinearAxis { Position = AxisPosition.Left, Title = "Displacement" });

            PlotModel = plotModel;
        }

        private Complex CalculateHarmonic(double[] data, int harmonic, int numSamples, int T)
        {
            double realPart = 0;
            double imagPart = 0;
            for (int i = 0; i < numSamples; i++)
            {
                double angle = 2 * Math.PI * harmonic * i / numSamples;
                realPart += data[i] * Math.Cos(angle);
                imagPart -= data[i] * Math.Sin(angle);
            }
            realPart /= numSamples;
            imagPart /= numSamples;

            return new Complex(realPart, imagPart);
        }

        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}
